#!/bin/bash
# 
# 
# 
# 
#
# 
# 
# 
# 
# 
# 
#
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 
# 


# Max number of arguments, empty vaule = unlimited arguments
SCRIPT_MAX_ARGS=

SCRIPT_NAME="$(basename "$0")"

# each run uses temporary files in its own folder.
INSTANCE=/var/tmp/${SCRIPT_NAME}${$}
[ -d ${INSTANCE} ] || mkdir ${INSTANCE}
[ -d ${INSTANCE} ] && rm -rf ${INSTANCE}
mkdir ${INSTANCE}

# Stores the name of the UCS file.
ARGS=()
# Stores option flags
OPTIONS=()
# For returning value after calling CHKOPT
OPTION_VALUE=

usage () {
  echo "Usage: $SCRIPT_NAME [-H | --strip-home] [ --exclude PATTERN ] UCS_file

Options:
  --exclude			Specify file/path pattern to exclude from new UCS.
  --strip-home	Exclude /home directory contents and subdirectories from new UCS archive.
  -q						No output
  -v						Show verbose UCS statistics.
  -h, --help   display this help and exit
"  
}


# Show help and exit if no arguments provided.
(( ${#} )) || {
	usage
	exit 1
}
	
parse_options() {
  while (( ${#}>0 )); do
    opt="$1"
    arg="$2"
    
    case "$opt" in
      --exclude)
        SETOPT "EXCLUDE_PATTERNS" "$arg" 1
        echo "OPTIONS -----> ${OPTIONS}"
        shift
        ;;
      -H|--strip-home)
        SETOPT "STRIP_HOME"
        ;;
      -d|--debug)
        SETOPT "DEBUG"
        ;;
      -e|--option-needs-do-something-right-away)
        do_something
        ;;
      -h|--help)
        usage
        exit 0
        ;;
      -q)
        SETOPT "SILENT"
        ;;
      -*)
        echo "$SCRIPT_NAME: invalid option -- '$opt'" >&2
        echo "Try \`$SCRIPT_NAME --help' for more information." >&2
        exit 1
        ;;
      *)
        if [[ ! -z $SCRIPT_MAX_ARGS ]] && (( ${#ARGS[@]} == $SCRIPT_MAX_ARGS )); then
          echo "$SCRIPT_NAME: cannot accept any more arguments -- '$opt'" >&2
          echo "Try \`$SCRIPT_NAME --help' for more information." >&2
          exit 1
        else
          ARGS=("${ARGS[@]}" "$opt")
        fi
        ;;
    esac
    shift
  done
}


###########################
# Script Template Functions

# Stores options
# $1 - option name
# $2 - option value
# $3 - non-empty if value is not optional
SETOPT() {
  if [[ ! -z "$3" ]] && [[ -z "$2" ]]; then
    echo "$SCRIPT_NAME: missing option value -- '$opt'" >&2
    echo "Try \`$SCRIPT_NAME --help' for more information." >&2
    exit 1
  fi
  # XXX should check duplication, but doesn't really matter
  OPTIONS=("${OPTIONS[@]}" "$1" "$2")
}

# Checks if an option is set, also set OPTION_VALUE.
# Returns 0 if found, 1 otherwise.
CHKOPT() {
  local i opt needle="$1"
  for (( i=0; i<${#OPTIONS[@]}; i+=2 )); do
    opt="${OPTIONS[i]}"
    if [[ "$opt" == "$needle" ]]; then
      OPTION_VALUE="${OPTIONS[i+1]}"
      return 0
    fi
  done
  OPTION_VALUE=
  return 1
}

parse_options "$@"


if CHKOPT "STRIP_HOME"; then
	if CHKOPT "EXCLUDE_PATTERNS"; then
  	EXCLUDE_PATTERNS=${OPTION_VALUE}'^/home/*'
	else
  	EXCLUDE_PATTERNS='^/home/*'
	fi
else
	if ! CHKOPT "EXCLUDE_PATTERNS"; then
    echo "$SCRIPT_NAME: missing --strip-home or --exclude"
    echo "Must have one or the other to do anything useful"
    echo "Try \`$SCRIPT_NAME --help' for more information." >&2
    exit 1
  fi
fi

[ "$ARGS" ] || {
	echo "$SCRIPT_NAME: No UCS file specified."
	echo "Try \`$SCRIPT_NAME --help' for more information." >&2
	exit 1
}

[ -f "${ARGS}" ] || {
	echo "$SCRIPT_NAME: UCS file ${ARGS} doesn't exist."
	exit 1
}


UCSFILE=${ARGS}
UCSPATH=`dirname ${UCSFILE}`
STEM=`basename ${UCSFILE} .ucs`
UCSFILE_NEW=${UCSPATH}/${STEM}_clean.ucs
GZFILE=${UCSPATH}/${STEM}.gz



echo Processing UCS $UCSFILE.

cp ${UCSFILE} ${GZFILE}
IMFILE=`gunzip -l --name ${GZFILE} | awk '// {o=$NF} END {printf o}'`
echo IMFILE is ${IMFILE}
gunzip -fN ${GZFILE}

#cp -f ${UCSFILE} ${UCSFILE_NEW}
echo Extracting SPEC-Files and SPEC-Manifest from ${UCSFILE}
tar -xf $UCSFILE -C ${INSTANCE} SPEC-Files SPEC-Manifest
grep -f  ucs_exclude ${INSTANCE}/SPEC-Files > ${INSTANCE}/specfile_exclude
grep -vf ucs_exclude ${INSTANCE}/SPEC-Files > ${INSTANCE}/specfile_include
mv -f ${INSTANCE}/specfile_include ${INSTANCE}/SPEC-Files

# Sort excluded_names by reverse line length.  Prevents tar from complaining that a file/path doesn't exist.
awk '{gsub("^\/","",$2) ; print length($2),$2}' ${INSTANCE}/specfile_exclude 2>/dev/null | sort -rn | cut -d " " -f2- > ${INSTANCE}/excluded_names

awk '{print $2}' ${INSTANCE}/specfile_exclude 2>/dev/null > ${INSTANCE}/excluded_names_full
awk '{gsub("^\/","",$2) ; print $2}' ${INSTANCE}/SPEC-Files 2>/dev/null > ${INSTANCE}/included_names

grep -xvf ${INSTANCE}/excluded_names_full ${INSTANCE}/SPEC-Manifest > ${INSTANCE}/manifest_include
mv -f ${INSTANCE}/manifest_include ${INSTANCE}/SPEC-Manifest
echo Creating ${UCSPATH}/ucs_removed_files
# Save the files that are being excluded from the clean ucs.
[ -d ${UCSPATH}/ucs_removed_files ]  && rm -rf ${UCSPATH}/ucs_removed_files
mkdir ${UCSPATH}/ucs_removed_files

tar -xf ${IMFILE} -C ${UCSPATH}/ucs_removed_files -T ${INSTANCE}/excluded_names
tar --delete -f ${IMFILE} -T ${INSTANCE}/excluded_names
tar --delete -f ${IMFILE} SPEC-Manifest
tar --delete -f ${IMFILE} SPEC-Files
tar -uf ${IMFILE} -C ${INSTANCE} SPEC-Files SPEC-Manifest
gzip -cN ${IMFILE}>${UCSFILE_NEW}

